/// 
/// MaDAson - Toolkit for Model Driven Software Development
/// 
/// Copyright [2006] Marcus Lankenau
/// 
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///  
///     http://www.apache.org/licenses/LICENSE-2.0
///  
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// 

using System;
using System.Collections.Generic;
using System.Text;
using Madason.MetaModel;

namespace Madason.ModelUtil.ModelTransformation
{
	/// <summary>
	/// Convert a E-R-Diagram to Entity Diagram for DAO generation
	/// </summary>
	public class ERToEntity
	{
		private Model model;


		/// <summary>
		/// sample: SOME_COLUMN_NAME -> someColumnName
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		public static string ConvertToCamelCase(string name)
		{
			if (name == null) return null;
			StringBuilder result = new StringBuilder();
			bool first = true;
			foreach (string part in name.Split("_".ToCharArray()))
			{
				StringBuilder buffer = new StringBuilder(part);
				for (int i = 0; i < buffer.Length; i++)
				{
					if (first || i > 0)
						buffer[i] = Char.ToLower(buffer[i]);
					else
						buffer[i] = Char.ToUpper(buffer[i]);
				}
				result.Append(buffer.ToString());
				first = false;
			}
			return result.ToString();
		}

		/// <summary>
		/// sample: SOME_TABLE_NAME -> SomeTableName
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		public static string ConvertToPascalCase(string name)
		{
			if (name == null) return null;
			StringBuilder result = new StringBuilder();
			bool first = true;
			foreach (string part in name.Split("_".ToCharArray()))
			{
				StringBuilder buffer = new StringBuilder(part);
				for (int i = 0; i < buffer.Length; i++)
				{
					if (i > 0)
						buffer[i] = Char.ToLower(buffer[i]);
					else
						buffer[i] = Char.ToUpper(buffer[i]);
				}
				result.Append(buffer.ToString());
				first = false;
			}
			return result.ToString();
		}


		protected string FindOrCreateType(string name)
		{
			Class cls = model.FindClassByName(name);
			if (cls != null) return cls.Id;

			cls = new Datatype();
			cls.Name = name;
			cls.Namespace = model;
			cls.Id = Guid.NewGuid().ToString();
			model.Classes.Insert(0, cls);

			return cls.Id;
		}


		protected void TransformAttribute(Madason.MetaModel.Attribute attr)
		{
			attr.Name = ConvertToCamelCase(attr.Name);

			Class type = attr.Type;
			
			if (type.Name == "NUMBER") attr.TypeId = FindOrCreateType("int");
			if (type.Name == "VARCHAR2") attr.TypeId = FindOrCreateType("String");


		}


		protected void TransformClass(Class cls)
		{
			foreach (Madason.MetaModel.Attribute attr in cls.Attributes)
			{
				TransformAttribute(attr);
			}
			if (!(cls is Datatype))
				cls.Name = ConvertToPascalCase(cls.Name);
		}

		public void TransformNamespace(Namespace ns)
		{
			foreach (Namespace childNs in ns.Namespaces)
			{
				TransformNamespace(childNs);
			}

			foreach (Class cls in ns.Classes)
			{
				TransformClass(cls);
			}
		}
		
		
		public void Transform(Model model)
		{
			this.model = model;
			TransformNamespace(model);
		}
	}
}
